/*
  Copyright 2018 Tobias Platen

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "sekai/JSONReader.h"
#include <fstream>
#include <iostream>
#include <jsoncpp/json/json.h>
#include <sndfile.h>
#include <stdio.h>

#define KEY(s) static const std::string key_##s = #s;

KEY(sndfile)
KEY(pulseLocations)
KEY(f0)

bool JSONReader::readFile(std::string fileName) {
  Json::Value root;
  std::ifstream file(fileName);
  file >> root;

  if (root.isMember(key_sndfile) && root[key_sndfile].isString()) {
    std::string tmp = root[key_sndfile].asString();
    SF_INFO info;
    SNDFILE *sf = sf_open(tmp.c_str(), SFM_READ, &info);
    dataLength = info.frames;
    samplerate = info.samplerate;
    data = new float[dataLength];
    sf_read_float(sf, data, dataLength);
    sf_close(sf);
  } else
    return false;

  if (root.isMember(key_pulseLocations) && root[key_pulseLocations].isArray()) {
    Json::Value tmp = root[key_pulseLocations];
    int size = tmp.size();
    pulseLocationsCount = size;
    pulseLocations = new int[size];
    for (int i = 0; i < size; i++) {
      pulseLocations[i] = tmp[i].asInt();
    }
  } else
    return false;

  if (root.isMember(key_f0) && root[key_f0].isNumeric())
    f0 = root[key_f0].asFloat();
  else
    return false;

  return true;
}

// TODO: test this function // create one json file and a wav file with constant
// pitch
bool JSONReader::copyIn(float *buffera, float *bufferb, float *ratio,
                        int buffer_length, float pos) {

  int i, j;
  int found = -1;
  int ref = pos * samplerate;
  int pulse0 = 0;
  for (i = 0; i < pulseLocationsCount - 1; i++) {
    if (pulseLocations[i - 1] <= ref && pulseLocations[i] > ref) {
      found = i;
      break;
    }
  }
  if (ref < pulseLocations[0]) {
    found = 0;
    pulse0 = 1;
  }
  if (found >= 0) {
    for (i = 0; i < buffer_length; i++) {
      j = i + pulseLocations[found - 1];
      if (j > 0 && j < dataLength)
        buffera[i] = data[j];
      else
        buffera[i] = 0;
    }
    for (i = 0; i < buffer_length; i++) {
      j = i + pulseLocations[found];
      if (j > 0 && j < dataLength)
        bufferb[i] = data[j];
      else
        bufferb[i] = 0;
    }
    if (pulse0)
      *ratio = 0.5;
    else {
      float zz = pulseLocations[found - 1] - pulseLocations[found];
      float nn = pulseLocations[found - 1] - ref;
      *ratio = nn / zz;
    }
    return true;
  }
  return false;
}
